﻿using System;
using System.Text;
using System.Threading;
using ChatClient.Handler;
using ChatCommon;
using ChatCommon.Packets;
using Lidgren.Network;
using Microsoft.Win32;
using NetBrick.Client;
using NetBrick.Common;

namespace ChatClient
{
    internal class ChatExampleClient : Client
    {
        private readonly string _name;

        public bool Connected { get; private set; }

        public ChatExampleClient(string name)
            : base("ChatExample")
        {
            Connected = false;
            _name = name;
        }

        protected override void Init()
        {
            Log.Init();
            Console.Title = "ChatExample " + _name;
            DebugInfo("Initializing chat client...");
            new Thread(() =>
            {
                while (!Environment.HasShutdownStarted)
                {
                    if (!Connected) continue;
                    var message = Console.ReadLine();
                    var chatPacket = new ChatPacket.Request(message);
                    SendPacket(ChatPacketCode.ChatMessageRequest, chatPacket, NetDeliveryMethod.ReliableOrdered);
                }
                Disconnect("User logged out.");
                while (Connected)
                {
                }
            }).Start();

            SystemEvents.SessionEnding += (s,e) =>
            {
                while (true)
                {
                    if (!Environment.HasShutdownStarted) continue;
                    Disconnect("User disconnected.");
                    while (Connected)
                    {
                    }
                    break;
                }
            };
            Packet.Instance.Register(ChatPacketCode.Authenticate, typeof (AuthenticatePacket));
            Packet.Instance.Register(ChatPacketCode.ChatMessageRequest, typeof (ChatPacket.Request));
            Packet.Instance.Register(ChatPacketCode.ChatMessageEvent, typeof (ChatPacket.Event));
            AddPacketHandler(ChatPacketCode.ChatMessageEvent, new ChatPacketHandler(this));
            DebugInfo("Initialized chat client.");
            DebugInfo("Connecting to the server...");
            Connect("localhost", 35565);
        }

        public override void DebugInfo(string message, params object[] arg)
        {
            Log.Info(message, arg);
        }

        public override void DebugWarn(string message, params object[] arg)
        {
            Log.Warn(message, arg);
        }

        public override void DebugError(string message, params object[] arg)
        {
            Log.Error(message, arg);
        }

        public override void DebugSevere(string message, params object[] arg)
        {
            Log.Severe(message, arg);
        }

        protected override void OnDisconnect(string reason)
        {
            if (Connected)
            {
                DebugInfo("Disconnected from the server. Reason: {0}", reason);
                Connected = false;
            }
            else
            {
                DebugError("Failed to connect to server. Reason: {0}", reason);
            }
        }

        protected override void OnConnect()
        {
            Connected = true;
            DebugInfo("Connected to the server.");
            EstablishEncryption();
            new Thread(() =>
            {
                while (!EncryptionAvailable)
                {
                }
                Console.WriteLine("Encryption available - authenticating ...");
                var authPacket = new AuthenticatePacket(Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(_name))));
                SendPacket(ChatPacketCode.Authenticate, authPacket, NetDeliveryMethod.ReliableOrdered);
            }).Start();
            new Thread(() =>
            {
                while (!Environment.HasShutdownStarted)
                {
                }
                Disconnect("Player disconnected.");
            }).Start();
        }
    }
}